; scrsaver.asm
; Screen saver implementation

	.include "common.inc"
	.include "global.inc"
	.include "timer.inc"
	.include "util.inc"
	.include "window.inc"
	.include "screen.inc"
	.include "string.inc"
	.include "disk.inc"
	.include "config.inc"
	
	.export init_saver
	.export do_saver_1s
	
	.segment "DATA"

ia_timeout:	.word 180		; 3 min.
ia_counter:	.res 2

vic_save:	.res 16
	
	.segment "CODE"
	
init_saver:	ldx #CONFIG_SCREEN_TIMEOUT_LO
			jsr get_config
			sta ia_timeout
			ldx #CONFIG_SCREEN_TIMEOUT_HI
			jsr get_config
			sta ia_timeout+1
			jsr reset_counter
			lda #<handle_activity
			ldx #>handle_activity
			jmp set_actfun
			
handle_activity:
			; fall through

reset_counter:
			lda ia_timeout
			sta ia_counter
			lda ia_timeout+1
			sta ia_counter+1
			rts

;
;	Decrement inactivity timeout & start saver if 0
;

do_saver_1s:
			lda ia_counter
			bne @noufl
			lda ia_counter+1
			beq run_saver
			dec ia_counter+1
@noufl:		dec ia_counter			
			rts

;
;	Screen saver exec
;

	TEXT_LEN = 5
	SHIFT_HEIGHT = 20
	BUFFER_BASE = scratchbuf1+TEXT_LEN+1

run_saver:	; save state
			ldx #15
@savvic:	lda VIC_BASE, x
			sta vic_save, x
			dex
			bpl @savvic
			
			lda #0
			ldx #32*(TEXT_LEN+1)
@clrbm:		sta VIDEO_BASE+15, x
			sta BUFFER_BASE-1, x
			dex
			bne @clrbm
			ldx #TEXT_LEN
@clrfrm:	sta BUFFER_BASE-TEXT_LEN-1, x
			sta BUFFER_BASE+32*(TEXT_LEN+1), x
			dex
			bpl @clrfrm
			
			; init
			lda #8
			sta VIC_BASE+15
			lda VIC_BASE+2	; prepare screen
			and #$80
			ora #TEXT_LEN+1
			sta VIC_BASE+2
			lda #5
			sta VIC_BASE+3
			ldx #TEXT_LEN
@setbm:		txa
			asl
			ora #1
			sta VIDEO_BASE, x
			sta VIDEO_BASE+TEXT_LEN+1, x
			inc VIDEO_BASE+TEXT_LEN+1, x
			dex
			bpl @setbm
			
			ldx #0
			stx scr_h
			stx scr_v
			inx
			stx scr_dx
			inx
			stx scr_dy
			lda VIC_BASE
			sta scr_h0
			lda VIC_BASE+1
			sta scr_v0
			lda scr_dim_x
			lsr
			lsr
			clc
			sbc #TEXT_LEN*2
			sta scr_hm
			lda scr_dim_y
			lsr
			clc
			sbc #8
			sta scr_vm
		
			; main saver loop
@svloop:	
			jsr showtext
			lda scr_dx
			sta l_dx
			bpl @nondx
			lda #3
			sta loop_cnt
@ndx:		jsr shrgt
			dec loop_cnt
			bne @ndx
@nondx:		lda scr_dy
			sta l_dy
			bpl @nondy
			lda #3
			sta loop_cnt
@ndy:		jsr shdn
			dec loop_cnt
			bne @ndy
@nondy:
			lda scr_h
			clc
			adc scr_dx
			sta scr_h
			cmp scr_hm
			bcc @no_bh
			lda scr_dx
			eor #$FF
			tax
			inx
			stx scr_dx
@no_bh:		lda scr_v
			clc
			adc scr_dy
			sta scr_v
			cmp scr_vm
			bcc @no_bv
			lda scr_dy
			eor #$FF
			tax
			inx
			stx scr_dy
@no_bv:	
			jsr wait_refresh

			clc
			lda scr_v0
			adc scr_v
			tay
			clc
			lda scr_h0
			adc scr_h
			tax
			
			stx VIC_BASE
			sty VIC_BASE+1
			jsr show_bm

			lda #3
			sta loop_cnt

@wait_loop:	lda l_dx
			bmi @shl
			jsr shrgt
			jmp @lrdone
@shl:		jsr shlft
@lrdone:	lda l_dy
			bmi @shup
			jsr shdn
			jmp @uddone
@shup:		jsr shup
@uddone:
			jsr wait_refresh
			jsr show_bm
						
			dec loop_cnt
			bne @wait_loop
			
			jsr has_rtc
			beq @skiptime
			
			jsr get_time
			cmp time_min
			beq @skiptime
			stx time_min
			lda #<ststr
			ldx #>ststr
			jsr ssetbuf
			jsr sclear
			jsr get_timestr

@skiptime:			
			lda ia_counter
			ora ia_counter+1
			bne @quitsave
			jmp @svloop
			
@quitsave:
			; restore state
			ldx #15
@resvic:	lda vic_save, x
			sta VIC_BASE, x
			dex
			bpl @resvic
			
			jsr clr_timer
			jmp redraw_screen

;
;	Copy bitmap buffer to screen
;

show_bm:	ldx #32*(TEXT_LEN+1)
@shwbm:		lda BUFFER_BASE-1, x
			sta CHAR_BASE+15, x
			dex
			bne @shwbm
			rts

;
;	Shift text right
;

shrgt:		ldx #SHIFT_HEIGHT-1
@shrlp:		lsr BUFFER_BASE, x
			ror BUFFER_BASE+32, x
			ror BUFFER_BASE+64, x
			ror BUFFER_BASE+96, x
			ror BUFFER_BASE+128, x
			ror BUFFER_BASE+160, x
			dex
			bpl @shrlp
			rts

;
;	Shift text left
;

shlft:		ldx #SHIFT_HEIGHT-1
@shllp:		asl BUFFER_BASE+160, x
			rol BUFFER_BASE+128, x
			rol BUFFER_BASE+96, x
			rol BUFFER_BASE+64, x
			rol BUFFER_BASE+32, x
			rol BUFFER_BASE, x
			dex
			bpl @shllp
			rts

;
;	Shift text down
;

shdn:		ldx #(TEXT_LEN+1)*32
@shdnlp:	lda BUFFER_BASE-2, x
			sta BUFFER_BASE-1, x
			dex
			bne @shdnlp
			rts

;
;	Shift text up
;

shup:		ldx #0
@shuplp:	lda BUFFER_BASE+1, x
			sta BUFFER_BASE, x
			inx
			cpx #(TEXT_LEN+1)*32
			bcc @shuplp
			lda #0
			sta BUFFER_BASE+31
			sta BUFFER_BASE+63
			sta BUFFER_BASE+95
			sta BUFFER_BASE+127
			sta BUFFER_BASE+159
			rts

;
; display text on save-screen 
;

showtext:	lda #0
			sta textpos
			lda #<BUFFER_BASE
			sta reg0
			lda #>BUFFER_BASE
			sta reg0+1
@showch:	ldx textpos
			cpx #TEXT_LEN+1
			beq @finst
			lda savetext, x
			ldx #8
			jsr bmul
			sta reg1
			txa
			ora #$80
			sta reg1+1
			ldy #7
@cpbm:		lda (reg1), y
			pha
			tya
			asl
			tay
			pla
			sta (reg0), y
			iny
			sta (reg0), y
			tya
			lsr
			tay
			dey
			bpl @cpbm
			ldx #3			; clr next 3 lines
			ldy #16
			lda #0
@clrlines:	sta (reg0), y
			iny
			dex
			bne @clrlines
			clc
			lda reg0
			adc #32
			sta reg0
			lda reg0+1
			adc #0
			sta reg0+1
			inc textpos
			bne @showch
			
@finst:		rts

	.segment "DATA"

time_min:	.byte 0

scr_h0:		.res 1
scr_v0:		.res 1
scr_hm:		.res 1
scr_vm:		.res 1
scr_h:		.res 1
scr_v:		.res 1
scr_dx:		.res 1		
scr_dy:		.res 1
l_dx:		.res 1
l_dy:		.res 1

sgblk:		.res 1

loop_cnt:	.res 1

textpos:	.res 2
ststr:		.byte 5, 0
savetext:	.byte $16, $09, $03, $32, $30, $20
			